/*
 * volumegenerator.h
 *
 * Copyright 2012 The University of Auckland
 *
 *  Created on: 2/07/2012
 *      Author: cvan680
 */

#ifndef VRN_VOLUMEGENERATOR_H_
#define VRN_VOLUMEGENERATOR_H_

//#include "voreen/core/processors/renderprocessor.h"
#include "voreen/core/processors/volumeprocessor.h"
#include "voreen/core/ports/allports.h"
#include "voreen/core/datastructures/volume/volumeram.h"
#include "voreen/core/datastructures/volume/volume.h"
#include "voreen/core/datastructures/volume/volumecollection.h"
#include "voreen/core/datastructures/volume/volumefactory.h"
#include "voreen/core/properties/intproperty.h"
#include "voreen/core/properties/boolproperty.h"
#include "voreen/core/properties/buttonproperty.h"

namespace voreen {

class VolumeGenerator : public VolumeProcessor {
public:
	VolumeGenerator();

    // virtual constructor
    virtual Processor* create() const;

    // documentary functions
    virtual std::string getClassName() const { return "VolumeGenerator";       }
    virtual std::string getCategory() const  { return "Data Generation";      }
    virtual CodeState getCodeState() const   { return CODE_STATE_EXPERIMENTAL; }

protected:
    virtual void setDescriptions() {
        setDescription("Generates a VolumeCollection with synthetic data for use on my thesis processor. "
        			   "The volumes are always added in order, scalar fields first, then vector and then tensor fields."
        			   "Use the VolumeSelector widget to select individual volumes: note that the selector is zero-based."
        			   "Remember to click 'update' to update output port.");
    }

    // actual rendering code
    virtual void process();

    /// loads the shader
    virtual void initialize() throw (VoreenException);

    /// frees the shader
    virtual void deinitialize() throw (VoreenException);

    void onXDimensionsChange();
    void onYDimensionsChange();
    void onZDimensionsChange();

    void update();

    Volume* generateScalarVolumeSimple();
    Volume* generateScalarVolume();
    Volume* generateScalarVolume2();
    Volume* generateScalarVolumeHelix();
    Volume* generateVectorVolume();
    Volume* generateVectorVolume2();
    Volume* generateVectorVolumeWaves();
    Volume* generateVectorVolumeCircles();
    Volume* generateVectorVolumeCircle(float ax, float ay, float angular_velocity);
    Volume* generateVectorVolumeSingularities();
    Volume* generateVectorVolume100();
    Volume* generateVectorVolume200();
    Volume* generateTensorVolume();

    // NEW ONES
    Volume* saddleVectorVolume();

    // TEMP method to help calculate eigenvectors
    tgt::vec2 calcEigenvector(tgt::vec2 c1, tgt::vec2 c2, bool show);

private:

    /* TODO perhaps give an interface where users can choose how many of each field-type they want,
     * 		e.g. 3 scalar fields and 2 vector fields
     */

    // this output port outputs all volumes in a collection.
    VolumeCollectionPort outport;

    IntProperty dimension_x_prop;
    IntProperty dimension_y_prop;
    IntProperty dimension_z_prop;
    BoolProperty dimensions_cubed_prop;

    // these properties record the number of datasets of each type to create
    IntProperty num_scalar_volumes_prop;
    IntProperty num_vector_volumes_prop;
    IntProperty num_tensor_volumes_prop;

    ButtonProperty update_prop;

    VolumeFactory* volumefactory;

    VolumeCollection* collection_;

    float calculateVectorMagnitude( tgt::vec3 v );
    tgt::vec3 normalizeVector( tgt::vec3 v );
};

} // namespace

#endif /* VRN_VOLUMEGENERATOR_H_ */
